/*
 * Copyright 2002-2024 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.core.convert.support;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.CopyOnWriteArraySet;

import org.jspecify.annotations.Nullable;

import org.springframework.core.DecoratingProxy;
import org.springframework.core.ResolvableType;
import org.springframework.core.convert.ConversionFailedException;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.ConditionalConverter;
import org.springframework.core.convert.converter.ConditionalGenericConverter;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;
import org.springframework.core.convert.converter.ConverterRegistry;
import org.springframework.core.convert.converter.GenericConverter;
import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.StringUtils;

/**
 * Base {@link ConversionService} implementation suitable for use in most environments.
 * Indirectly implements {@link ConverterRegistry} as registration API through the
 * {@link ConfigurableConversionService} interface.
 *
 * @author Keith Donald
 * @author Juergen Hoeller
 * @author Chris Beams
 * @author Phillip Webb
 * @author David Haraburda
 * @since 3.0
 */
public class GenericConversionService implements ConfigurableConversionService {

	/**
	 * General NO-OP converter used when conversion is not required.
	 */
	private static final GenericConverter NO_OP_CONVERTER = new NoOpConverter("NO_OP");

	/**
	 * Used as a cache entry when no converter is available.
	 * This converter is never returned.
	 */
	private static final GenericConverter NO_MATCH = new NoOpConverter("NO_MATCH");


	//所有的转化器存储集合
	private final Converters converters = new Converters();

	private final Map<ConverterCacheKey, GenericConverter> converterCache = new ConcurrentReferenceHashMap<>(64);


	// ConverterRegistry implementation

	@Override
	public void addConverter(Converter<?, ?> converter) {
		ResolvableType[] typeInfo = getRequiredTypeInfo(converter.getClass(), Converter.class);
		if (typeInfo == null && converter instanceof DecoratingProxy decoratingProxy) {
			typeInfo = getRequiredTypeInfo(decoratingProxy.getDecoratedClass(), Converter.class);
		}
		if (typeInfo == null) {
			throw new IllegalArgumentException("Unable to determine source type <S> and target type <T> for your " +
					"Converter [" + converter.getClass().getName() + "]; does the class parameterize those types?");
		}
		addConverter(new ConverterAdapter(converter, typeInfo[0], typeInfo[1]));
	}

	@Override
	public <S, T> void addConverter(Class<S> sourceType, Class<T> targetType, Converter<? super S, ? extends T> converter) {
		addConverter(new ConverterAdapter(
				converter, ResolvableType.forClass(sourceType), ResolvableType.forClass(targetType)));
	}

	@Override
	public void addConverter(GenericConverter converter) {
		this.converters.add(converter);
		invalidateCache();
	}

	@Override
	public void addConverterFactory(ConverterFactory<?, ?> factory) {
		ResolvableType[] typeInfo = getRequiredTypeInfo(factory.getClass(), ConverterFactory.class);
		if (typeInfo == null && factory instanceof DecoratingProxy decoratingProxy) {
			typeInfo = getRequiredTypeInfo(decoratingProxy.getDecoratedClass(), ConverterFactory.class);
		}
		if (typeInfo == null) {
			throw new IllegalArgumentException("Unable to determine source type <S> and target type <T> for your " +
					"ConverterFactory [" + factory.getClass().getName() + "]; does the class parameterize those types?");
		}
		addConverter(new ConverterFactoryAdapter(factory,
				new ConvertiblePair(typeInfo[0].toClass(), typeInfo[1].toClass())));
	}

	@Override
	public void removeConvertible(Class<?> sourceType, Class<?> targetType) {
		this.converters.remove(sourceType, targetType);
		invalidateCache();
	}


	// ConversionService implementation

	@Override
	public boolean canConvert(@Nullable Class<?> sourceType, Class<?> targetType) {
		Assert.notNull(targetType, "Target type to convert to cannot be null");
		return canConvert((sourceType != null ? TypeDescriptor.valueOf(sourceType) : null),
				TypeDescriptor.valueOf(targetType));
	}

	@Override
	public boolean canConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
		Assert.notNull(targetType, "Target type to convert to cannot be null");
		return (sourceType == null || getConverter(sourceType, targetType) != null);
	}

	/**
	 * Return whether conversion between the source type and the target type can be bypassed.
	 * <p>More precisely, this method will return true if objects of sourceType can be
	 * converted to the target type by returning the source object unchanged.
	 * @param sourceType context about the source type to convert from
	 * (may be {@code null} if source is {@code null})
	 * @param targetType context about the target type to convert to (required)
	 * @return {@code true} if conversion can be bypassed; {@code false} otherwise
	 * @throws IllegalArgumentException if targetType is {@code null}
	 * @since 3.2
	 */
	public boolean canBypassConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
		Assert.notNull(targetType, "Target type to convert to cannot be null");
		return (sourceType == null || getConverter(sourceType, targetType) == NO_OP_CONVERTER);
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> @Nullable T convert(@Nullable Object source, Class<T> targetType) {
		Assert.notNull(targetType, "Target type to convert to cannot be null");
		return (T) convert(source, TypeDescriptor.forObject(source), TypeDescriptor.valueOf(targetType));
	}

	@Override
	public @Nullable Object convert(@Nullable Object source, @Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
		Assert.notNull(targetType, "Target type to convert to cannot be null");
		if (sourceType == null) {
			Assert.isTrue(source == null, "Source must be [null] if source type == [null]");
			return handleResult(null, targetType, convertNullSource(null, targetType));
		}
		if (source != null && !sourceType.getObjectType().isInstance(source)) {
			throw new IllegalArgumentException("Source to convert from must be an instance of [" +
					sourceType + "]; instead it was a [" + source.getClass().getName() + "]");
		}
		GenericConverter converter = getConverter(sourceType, targetType);
		if (converter != null) {
			Object result = ConversionUtils.invokeConverter(converter, source, sourceType, targetType);
			return handleResult(sourceType, targetType, result);
		}
		return handleConverterNotFound(source, sourceType, targetType);
	}

	@Override
	public String toString() {
		return this.converters.toString();
	}


	// Protected template methods

	/**
	 * Template method to convert a {@code null} source.
	 * <p>The default implementation returns {@code null} or the Java 8
	 * {@link java.util.Optional#empty()} instance if the target type is
	 * {@code java.util.Optional}. Subclasses may override this to return
	 * custom {@code null} objects for specific target types.
	 * @param sourceType the source type to convert from
	 * @param targetType the target type to convert to
	 * @return the converted null object
	 */
	protected @Nullable Object convertNullSource(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
		if (targetType.getObjectType() == Optional.class) {
			return Optional.empty();
		}
		return null;
	}

	/**
	 * Hook method to look up the converter for a given sourceType/targetType pair.
	 * First queries this ConversionService's converter cache.
	 * On a cache miss, then performs an exhaustive search for a matching converter.
	 * If no converter matches, returns the default converter.
	 * @param sourceType the source type to convert from
	 * @param targetType the target type to convert to
	 * @return the generic converter that will perform the conversion,
	 * or {@code null} if no suitable converter was found
	 * @see #getDefaultConverter(TypeDescriptor, TypeDescriptor)
	 */
	/**
	 * 获取用于将源类型转换为目标类型的转换器
	 * 此方法首先检查缓存中是否有适用于给定源类型和目标类型的转换器
	 * 如果没有找到，则尝试从注册的转换器中查找合适的转换器
	 * 如果仍然没有找到，那么会尝试获取一个默认的转换器
	 * 最后，如果无法找到或创建合适的转换器，则返回null
	 *
	 * @param sourceType 源类型的描述符
	 * @param targetType 目标类型的描述符
	 * @return 一个可用于转换的GenericConverter实例，如果找不到合适的转换器则返回null
	 */
	protected @Nullable GenericConverter getConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
	    // 创建一个缓存键，用于查找缓存中的转换器
	    ConverterCacheKey key = new ConverterCacheKey(sourceType, targetType);
	    // 尝试从缓存中获取转换器
	    GenericConverter converter = this.converterCache.get(key);
	    if (converter != null) {
	        // 如果找到的转换器不是NO_MATCH，则直接返回该转换器；否则返回null
	        return (converter != NO_MATCH ? converter : null);
	    }

	    // 如果缓存中没有找到转换器，则尝试从注册的转换器中查找
	    converter = this.converters.find(sourceType, targetType);
	    if (converter == null) {
	        // 如果没有找到合适的转换器，则尝试获取一个默认的转换器
	        converter = getDefaultConverter(sourceType, targetType);
	    }

	    if (converter != null) {
	        // 如果找到了合适的转换器，将其添加到缓存中，并返回该转换器
	        this.converterCache.put(key, converter);
	        return converter;
	    }

	    // 如果没有找到合适的转换器，将NO_MATCH添加到缓存中，表示没有找到转换器
	    this.converterCache.put(key, NO_MATCH);
	    return null;
	}

	/**
	 * Return the default converter if no converter is found for the given sourceType/targetType pair.
	 * <p>Returns a NO_OP Converter if the source type is assignable to the target type.
	 * Returns {@code null} otherwise, indicating no suitable converter could be found.
	 * @param sourceType the source type to convert from
	 * @param targetType the target type to convert to
	 * @return the default generic converter that will perform the conversion
	 */
	protected @Nullable GenericConverter getDefaultConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
		return (sourceType.isAssignableTo(targetType) ? NO_OP_CONVERTER : null);
	}


	// Internal helpers

	private ResolvableType @Nullable [] getRequiredTypeInfo(Class<?> converterClass, Class<?> genericIfc) {
		ResolvableType resolvableType = ResolvableType.forClass(converterClass).as(genericIfc);
		ResolvableType[] generics = resolvableType.getGenerics();
		if (generics.length < 2) {
			return null;
		}
		Class<?> sourceType = generics[0].resolve();
		Class<?> targetType = generics[1].resolve();
		if (sourceType == null || targetType == null) {
			return null;
		}
		return generics;
	}

	private void invalidateCache() {
		this.converterCache.clear();
	}

	private @Nullable Object handleConverterNotFound(
			@Nullable Object source, @Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {

		if (source == null) {
			assertNotPrimitiveTargetType(sourceType, targetType);
			return null;
		}
		if ((sourceType == null || sourceType.isAssignableTo(targetType)) &&
				targetType.getObjectType().isInstance(source)) {
			return source;
		}
		throw new ConverterNotFoundException(sourceType, targetType);
	}

	private @Nullable Object handleResult(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType, @Nullable Object result) {
		if (result == null) {
			assertNotPrimitiveTargetType(sourceType, targetType);
		}
		return result;
	}

	private void assertNotPrimitiveTargetType(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
		if (targetType.isPrimitive()) {
			throw new ConversionFailedException(sourceType, targetType, null,
					new IllegalArgumentException("A null value cannot be assigned to a primitive type"));
		}
	}


	/**
	 * Adapts a {@link Converter} to a {@link GenericConverter}.
	 */
	@SuppressWarnings("unchecked")
	private final class ConverterAdapter implements ConditionalGenericConverter {

		private final Converter<Object, Object> converter;

		private final ConvertiblePair typeInfo;

		private final ResolvableType targetType;

		public ConverterAdapter(Converter<?, ?> converter, ResolvableType sourceType, ResolvableType targetType) {
			this.converter = (Converter<Object, Object>) converter;
			this.typeInfo = new ConvertiblePair(sourceType.toClass(), targetType.toClass());
			this.targetType = targetType;
		}

		@Override
		public Set<ConvertiblePair> getConvertibleTypes() {
			return Collections.singleton(this.typeInfo);
		}

		@Override
		public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
			// Check raw type first...
			if (this.typeInfo.getTargetType() != targetType.getObjectType()) {
				return false;
			}
			// Full check for complex generic type match required?
			ResolvableType rt = targetType.getResolvableType();
			if (!(rt.getType() instanceof Class) && !rt.isAssignableFrom(this.targetType) &&
					!this.targetType.hasUnresolvableGenerics()) {
				return false;
			}
			return !(this.converter instanceof ConditionalConverter conditionalConverter) ||
					conditionalConverter.matches(sourceType, targetType);
		}

		@Override
		public @Nullable Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
			if (source == null) {
				return convertNullSource(sourceType, targetType);
			}
			return this.converter.convert(source);
		}

		@Override
		public String toString() {
			return this.typeInfo + " : " + this.converter;
		}
	}


	/**
	 * Adapts a {@link ConverterFactory} to a {@link GenericConverter}.
	 */
	@SuppressWarnings("unchecked")
	private final class ConverterFactoryAdapter implements ConditionalGenericConverter {

		private final ConverterFactory<Object, Object> converterFactory;

		private final ConvertiblePair typeInfo;

		public ConverterFactoryAdapter(ConverterFactory<?, ?> converterFactory, ConvertiblePair typeInfo) {
			this.converterFactory = (ConverterFactory<Object, Object>) converterFactory;
			this.typeInfo = typeInfo;
		}

		@Override
		public Set<ConvertiblePair> getConvertibleTypes() {
			return Collections.singleton(this.typeInfo);
		}

		@Override
		public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
			boolean matches = true;
			if (this.converterFactory instanceof ConditionalConverter conditionalConverter) {
				matches = conditionalConverter.matches(sourceType, targetType);
			}
			if (matches) {
				Converter<?, ?> converter = this.converterFactory.getConverter(targetType.getType());
				if (converter instanceof ConditionalConverter conditionalConverter) {
					matches = conditionalConverter.matches(sourceType, targetType);
				}
			}
			return matches;
		}

		@Override
		public @Nullable Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
			if (source == null) {
				return convertNullSource(sourceType, targetType);
			}
			return this.converterFactory.getConverter(targetType.getObjectType()).convert(source);
		}

		@Override
		public String toString() {
			return this.typeInfo + " : " + this.converterFactory;
		}
	}


	/**
	 * Key for use with the converter cache.
	 */
	private static final class ConverterCacheKey implements Comparable<ConverterCacheKey> {

		private final TypeDescriptor sourceType;

		private final TypeDescriptor targetType;

		public ConverterCacheKey(TypeDescriptor sourceType, TypeDescriptor targetType) {
			this.sourceType = sourceType;
			this.targetType = targetType;
		}

		@Override
		public boolean equals(@Nullable Object other) {
			return (this == other || (other instanceof ConverterCacheKey that &&
					this.sourceType.equals(that.sourceType)) &&
					this.targetType.equals(that.targetType));
		}

		@Override
		public int hashCode() {
			return this.sourceType.hashCode() * 29 + this.targetType.hashCode();
		}

		@Override
		public String toString() {
			return "ConverterCacheKey [sourceType = " + this.sourceType + ", targetType = " + this.targetType + "]";
		}

		@Override
		public int compareTo(ConverterCacheKey other) {
			int result = this.sourceType.getResolvableType().toString().compareTo(
					other.sourceType.getResolvableType().toString());
			if (result == 0) {
				result = this.targetType.getResolvableType().toString().compareTo(
						other.targetType.getResolvableType().toString());
			}
			return result;
		}
	}


	/**
	 * Manages all converters registered with the service.
	 *
	 */
	private static class Converters {

		// 全局转换器集合，用于存储所有通用的类型转换器
		// 使用CopyOnWriteArraySet确保线程安全，允许并发读写而不会引起竞争条件
		private final Set<GenericConverter> globalConverters = new CopyOnWriteArraySet<>();

		// 专用转换器映射，用于存储特定类型对的转换器集合
		// 使用ConcurrentHashMap确保线程安全，支持高并发访问和修改
		// 初始容量设为256以减少重新哈希的可能性
		private final Map<ConvertiblePair, ConvertersForPair> converters = new ConcurrentHashMap<>(256);

		/**
		 * 向转换器集合中添加一个新的通用转换器
		 * 此方法根据转换器的类型，将其添加到全局转换器集合或特定类型转换器集合中
		 *
		 * @param converter 要添加的通用转换器实例
		 */
		public void add(GenericConverter converter) {
		    // 获取转换器支持的可转换类型集合
		    Set<ConvertiblePair> convertibleTypes = converter.getConvertibleTypes();

		    // 如果转换器返回的可转换类型集合为null，进行特定处理
		    if (convertibleTypes == null) {
		        // 确保只有条件转换器才返回null可转换类型
		        Assert.state(converter instanceof ConditionalConverter,
		                "Only conditional converters may return null convertible types");

		        // 将符合条件的转换器添加到全局转换器集合中
		        this.globalConverters.add(converter);
		    }
		    else {
		        // 遍历转换器支持的可转换类型集合
		        for (ConvertiblePair convertiblePair : convertibleTypes) {
		            // 将转换器添加到匹配的可转换类型对应的转换器集合中
		            getMatchableConverters(convertiblePair).add(converter);
		        }
		    }
		}

		private ConvertersForPair getMatchableConverters(ConvertiblePair convertiblePair) {
			return this.converters.computeIfAbsent(convertiblePair, k -> new ConvertersForPair());
		}

		public void remove(Class<?> sourceType, Class<?> targetType) {
			this.converters.remove(new ConvertiblePair(sourceType, targetType));
		}

		/**
		 * Find a {@link GenericConverter} given a source and target type.
		 * <p>This method will attempt to match all possible converters by working
		 * through the class and interface hierarchy of the types.
		 * @param sourceType the source type
		 * @param targetType the target type
		 * @return a matching {@link GenericConverter}, or {@code null} if none found
		 */
		/**
		 * 查找可以将 sourceType 转换为 targetType 的转换器。
		 *
		 * @param sourceType 源类型的类型描述符
		 * @param targetType 目标类型的类型描述符
		 * @return 适合的 GenericConverter 实例，如果没有找到则返回 null
		 */
		public @Nullable GenericConverter find(TypeDescriptor sourceType, TypeDescriptor targetType) {
			// 遍历源类型和目标类型的完整类层次结构
			List<Class<?>> sourceCandidates = getClassHierarchy(sourceType.getType());
			List<Class<?>> targetCandidates = getClassHierarchy(targetType.getType());

			// 遍历所有可能的源类型和目标类型组合，以找到合适的转换器
			for (Class<?> sourceCandidate : sourceCandidates) {
				for (Class<?> targetCandidate : targetCandidates) {
					// 创建一个表示潜在转换的 ConvertiblePair 实例
					ConvertiblePair convertiblePair = new ConvertiblePair(sourceCandidate, targetCandidate);

					// 尝试获取能够处理此转换的已注册转换器
					GenericConverter converter = getRegisteredConverter(sourceType, targetType, convertiblePair);

					// 如果找到合适的转换器，则立即返回
					if (converter != null) {
						return converter;
					}
				}
			}

			// 如果在遍历所有可能性后仍未找到合适的转换器，则返回 null
			return null;
		}


		private @Nullable GenericConverter getRegisteredConverter(TypeDescriptor sourceType,
				TypeDescriptor targetType, ConvertiblePair convertiblePair) {

			// Check specifically registered converters
			ConvertersForPair convertersForPair = this.converters.get(convertiblePair);
			if (convertersForPair != null) {
				GenericConverter converter = convertersForPair.getConverter(sourceType, targetType);
				if (converter != null) {
					return converter;
				}
			}
			// Check ConditionalConverters for a dynamic match
			for (GenericConverter globalConverter : this.globalConverters) {
				if (((ConditionalConverter) globalConverter).matches(sourceType, targetType)) {
					return globalConverter;
				}
			}
			return null;
		}

		/**
		 * Returns an ordered class hierarchy for the given type.
		 * @param type the type
		 * @return an ordered list of all classes that the given type extends or implements
		 */
		/**
		 * 获取类的继承层次结构
		 *
		 * 此方法旨在获取指定类的所有父类和接口，形成一个完整的继承层次结构列表
		 * 它不仅包括直接父类，还包括间接父类，直到Object类它还处理数组类型和枚举类型的特殊情况
		 *
		 * @param type 要获取继承层次结构的类
		 * @return 包含类的继承层次结构的列表
		 */
		private List<Class<?>> getClassHierarchy(Class<?> type) {
		    // 初始化继承层次结构列表和已访问类的集合
		    List<Class<?>> hierarchy = new ArrayList<>(20);
		    Set<Class<?>> visited = new HashSet<>(20);

		    // 将初始类添加到继承层次结构中
		    addToClassHierarchy(0, ClassUtils.resolvePrimitiveIfNecessary(type), false, hierarchy, visited);

		    // 判断类型是否为数组
		    boolean array = type.isArray();

		    int i = 0;
		    // 遍历继承层次结构列表，添加父类和接口
		    while (i < hierarchy.size()) {
		        Class<?> candidate = hierarchy.get(i);
		        // 对于数组类型，获取其组件类型
		        candidate = (array ? candidate.componentType() : ClassUtils.resolvePrimitiveIfNecessary(candidate));

		        // 获取当前类的父类
		        Class<?> superclass = candidate.getSuperclass();
		        // 如果父类存在且不是Object或Enum类，则添加到继承层次结构中
		        if (superclass != null && superclass != Object.class && superclass != Enum.class) {
		            addToClassHierarchy(i + 1, candidate.getSuperclass(), array, hierarchy, visited);
		        }

		        // 添加当前类实现的接口到继承层次结构中
		        addInterfacesToClassHierarchy(candidate, array, hierarchy, visited);
		        i++;
		    }

		    // 如果初始类是枚举类型，添加Enum类及其接口到继承层次结构中
		    if (Enum.class.isAssignableFrom(type)) {
		        addToClassHierarchy(hierarchy.size(), Enum.class, false, hierarchy, visited);
		        addInterfacesToClassHierarchy(Enum.class, false, hierarchy, visited);
		    }

		    // 最后添加Object类到继承层次结构中，处理数组和非数组情况
		    addToClassHierarchy(hierarchy.size(), Object.class, array, hierarchy, visited);
		    addToClassHierarchy(hierarchy.size(), Object.class, false, hierarchy, visited);

		    // 返回完整的继承层次结构列表
		    return hierarchy;
		}

		private void addInterfacesToClassHierarchy(Class<?> type, boolean asArray,
				List<Class<?>> hierarchy, Set<Class<?>> visited) {

			for (Class<?> implementedInterface : type.getInterfaces()) {
				addToClassHierarchy(hierarchy.size(), implementedInterface, asArray, hierarchy, visited);
			}
		}

		private void addToClassHierarchy(int index, Class<?> type, boolean asArray,
				List<Class<?>> hierarchy, Set<Class<?>> visited) {

			if (asArray) {
				type = type.arrayType();
			}
			if (visited.add(type)) {
				hierarchy.add(index, type);
			}
		}

		@Override
		public String toString() {
			StringBuilder builder = new StringBuilder();
			builder.append("ConversionService converters =\n");
			for (String converterString : getConverterStrings()) {
				builder.append('\t').append(converterString).append('\n');
			}
			return builder.toString();
		}

		private List<String> getConverterStrings() {
			List<String> converterStrings = new ArrayList<>();
			for (ConvertersForPair convertersForPair : this.converters.values()) {
				converterStrings.add(convertersForPair.toString());
			}
			Collections.sort(converterStrings);
			return converterStrings;
		}
	}


	/**
	 * Manages converters registered with a specific {@link ConvertiblePair}.
	 */
	/**
	 * ConvertersForPair类用于管理一对类型之间的转换器
	 * 它提供添加转换器和获取特定类型对转换器的功能
	 */
	private static class ConvertersForPair {

		// 存储GenericConverter的双端队列，用于高效地添加和移除转换器
		private final Deque<GenericConverter> converters = new ConcurrentLinkedDeque<>();

		/**
		 * 添加一个GenericConverter到队列的前端
		 *
		 * @param converter 要添加的GenericConverter实例
		 */
		public void add(GenericConverter converter) {
			this.converters.addFirst(converter);
		}

		/**
		 * 根据源类型和目标类型获取合适的转换器
		 *
		 * @param sourceType  源类型的TypeDescriptor
		 * @param targetType  目标类型的TypeDescriptor
		 * @return 如果找到合适的转换器则返回它，否则返回null
		 */
		public @Nullable GenericConverter getConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
			for (GenericConverter converter : this.converters) {
				// 检查转换器是否为ConditionalGenericConverter，并验证其是否匹配给定的类型对
				if (!(converter instanceof ConditionalGenericConverter genericConverter) ||
						genericConverter.matches(sourceType, targetType)) {
					return converter;
				}
			}
			return null;
		}

		/**
		 * 重写toString方法，用于以逗号分隔的字符串形式输出转换器集合
		 *
		 * @return 转换器集合的字符串表示
		 */
		@Override
		public String toString() {
			return StringUtils.collectionToCommaDelimitedString(this.converters);
		}
	}


	/**
	 * Internal converter that performs no operation.
	 */
	private static class NoOpConverter implements GenericConverter {

		private final String name;

		public NoOpConverter(String name) {
			this.name = name;
		}

		@Override
		public @Nullable Set<ConvertiblePair> getConvertibleTypes() {
			return null;
		}

		@Override
		public @Nullable Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
			return source;
		}

		@Override
		public String toString() {
			return this.name;
		}
	}

}
